package com.hup.sb.view;

import com.hup.sb.model.MainConfig;
import com.hup.utils.commons.exception.AppCommonException;
import com.hup.utils.commons.start.DialogHelper;
import com.hup.utils.commons.start.LookThemeUtil;
import com.hup.utils.commons.start.SingletonAppManager;
import com.hup.utils.commons.start.SingletonAppManager.SingletonAppHandler;
import com.hup.utils.commons.start.StartupInfo;
import com.hup.utils.swing.FrameUtil;
import com.hup.utils.swing.FrameUtil.Gravity;
import com.hup.utils.swing.frame.BaseJWindow;
import com.hup.utils.swing.frame.SingletonWindowHelper;
import com.hup.utils.swing.frame.WindowEdgeHideHelper;
import com.hup.utils.swing.frame.WindowEdgeHideHelper.EdgeHideWindow;
import com.hup.utils.swing.frame.WindowLocationAdjustor;
import com.hup.utils.swing.frame.WindowLocationAdjustor.WindowLocationAdjustorCallback;
import com.hup.utils.swing.model.BaseWindowConfig;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.awt.Component;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Window;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author hugan
 * @date 2022/2/27
 */
@Slf4j
public class MainWindow extends BaseJWindow implements EdgeHideWindow {

    private static MainConfig config;

    private MainForm form;
    private final List<ShadeWindow> shadeWindows;

    @Getter
    private WindowEdgeHideHelper edgeHideHelper;
    private boolean hadInit;

    public static void startUp() {
        config = new MainConfig().loadFromFile();
        if (config.resetOnBoot) config.brightness = 100;
        try {
            SingletonAppManager.doStart(new MySingletonAppHandler());
        } catch (AppCommonException e) {
            throw e;
        } catch (Exception e) {
            throw new AppCommonException("单例端口号异常,MainConfig.appPort=[" + config.appPort + "]");
        }

        MainWindow mainWindow = new MainWindow();
        mainWindow.switchVisible(true);
        new AppTray(mainWindow).doShow();
    }

    private MainWindow() {
        super(StartupInfo.getApplicationChName());

        hadInit = false;
        initView();
        initListener();
        initConfig();
        hadInit = true;

        shadeWindows = new ArrayList<>();
        //updateShadeCount();//不需要,visible时会updateShadeCount()
    }

    private void initView() {
        form = new MainForm();
        setContentPane(form.root);

        setAlwaysOnTop(true);
        pack();
        setSize(getWidth(), (int) (200 * LookThemeUtil.getScreenScale()));
        FrameUtil.setLocation(this, Gravity.MID_R);
    }

    private void initListener() {
        WindowLocationAdjustor.bind(new LocationHandler());
        edgeHideHelper = WindowEdgeHideHelper.bind(this);

        form.btnHide.setActionListener(e -> switchVisible(false));
        form.btnExit.setActionListener(e -> onExit());

        form.alphaSetter.addChangeListener(e -> {
            if (!hadInit) return;
            int value = form.alphaSetter.getValue();
            boolean adjusting = form.alphaSetter.getValueIsAdjusting();
            log.debug("value={}, Adjusting={}", value, adjusting);
            if (adjusting) {
                config.setBrightness(value);
                updateShade();
            } else {
                config.save();
            }
        });

        /*
        监听显示器[数量,尺寸]
        使用 java.util.Timer
        不使用javax.swing.Timer: 执行任务时,在ui线程,可能会卡住ui
         */
        new Timer("screen-status").schedule(new TimerTask() {
            @Override
            public void run() {
                updateShadeCount();
            }
        }, 2000, 2000);
    }

    private void initConfig() {
        BaseWindowConfig windowConfig = config.windowConfig;
        if (windowConfig.loc != null) setLocation(windowConfig.loc);
        form.alphaSetter.setValue(config.brightness);
    }

    @Override
    public void setVisible(boolean b) {
        super.setVisible(b);
        if (b) updateShadeCount();
    }

    private void updateShade() {
        //alpha[0-全透明,1-不透明]
        float alpha = 1 - config.brightness / 100f;
        //log.info("alpha={}, visible={}", alpha, alpha != 0);

        shadeWindows.forEach(w -> w.updateShade(alpha));
    }

    /**
     * 根据屏幕数量 更新 shadeWindows[数量,尺寸]
     */
    private synchronized void updateShadeCount() {
        GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
        int oldSize = shadeWindows.size();
        int newSize = devices.length;
        //log.info("size={} -> {}", shadeWindows.size(), devices.length);

        //创建
        float alpha = 1 - config.brightness / 100f;
        for (int i = oldSize; i < newSize; i++) {
            //log.info("create={}", i);
            ShadeWindow shadeWindow = new ShadeWindow(devices[i]);
            shadeWindow.updateShade(alpha);
            shadeWindows.add(shadeWindow);
        }

        //删除
        for (int i = oldSize - 1; i >= newSize; i--) {
            //log.info("remove={}", i);
            ShadeWindow shadeWindow = shadeWindows.get(i);
            shadeWindow.dispose();
            shadeWindows.remove(i);
        }

        //更新尺寸
        for (int i = 0; i < newSize; i++) {
            shadeWindows.get(i).updateBounds(devices[i]);
        }
    }

    public void onExit() {
        boolean ok = DialogHelper.yesNo("确认[退出]?").show(this);
        if (ok) System.exit(0);
    }

    private class LocationHandler implements WindowLocationAdjustorCallback {

        @Override
        public Window getWindow() {
            return MainWindow.this;
        }

        @Override
        public Component[] getAdjustor() {
            return new Component[]{form.root};
        }

        @Override
        public void afterMoved(int x, int y, Boolean onTop, Boolean onLeft) {
            if (config.windowConfig.loc == null) config.windowConfig.loc = new Point();
            config.windowConfig.loc.x = x;
            config.windowConfig.loc.y = y;
            config.save();
        }

    }

    private static class MySingletonAppHandler implements SingletonAppHandler {
        @Override
        public int port() {
            return config.appPort;
        }

        @Override
        public String appTag() {
            return StartupInfo.getApplicationName();
        }

        @Override
        public void onAppReduplicateStart() {
            log.info("保持单例成功");
            SingletonWindowHelper.getWindow(MainWindow.class).switchVisible(true);
        }

        @Override
        public String portSettingFileDesc() {
            return "MainConfig.appPort";
        }
    }

}
